package Obstacle;

import be.kuleuven.cs.som.annotate.Basic;
import be.kuleuven.cs.som.annotate.Raw;

public class Door {
	
	/**
	 * A variable to store whether or not this door is open
	 */
	private boolean open;
	/**
	 * A variable to store in which wall this door is set
	 */
	private Wall wall;
	/**
	 * A variable to store whether or not a door is terminated
	 */
	private boolean isTerminated;
	
	/**
     * A constructor to initialize a door
     * 
     * @post ...
     * 		|new.isOpen() == true
     * @post ...
     * 		|new.isTerminated == false
     */
	public Door(){
		open = false;
		isTerminated = false;
		
	}
	

	/**
     * A constructor to initialize a door
     * 
     * @param wall
     * 			the wall in which you wish to construct this door
     * @post ...
     * 		|if (wall == null)
     * 		|new.isTerminated() == true
     * @post ...
     * 		|if (!new.hasWall()) 
     * 		|then new.isTerminated == true
     * @post ...
     * 		|new.getWall() == wall
     * 
     * 
     */
	public Door(Wall wall){
		if (wall != null){
			wall.setDoor(this);
			if (this.hasWall() == false)
				terminate();
			else isTerminated = false;
		}
		else{
			terminate();
		}
	}
	
	/**
     * A constructor to initialize a door
     * 
     * @param open
     * 			true if you wish to open the door
     * @post ...
     * 		|if (wall == null)
     * 		|new.isTerminated() == true
     * @post ...
     * 		|if (!new.hasWall()) 
     * 		|then new.isTerminated == true
     * @post ...
     * 		|new.getWall() == wall
     * @post ...
     * 		@new.isOpen() == open 
     * 
     */
	public Door(boolean open, Wall wall){
		if (wall != null){
			wall.setDoor(this); 
			if (open == true){
			openDoor();
			}
			else{
			closeDoor();
			}
			if (this.hasWall() == false){
				terminate();
			}
			else isTerminated = false;
		}
		else {
			terminate();
		}
	}
	
	/**
	 * A method to open a door
	 * 
	 * @post ...
	 * 		|new.isOpen() == true
	 */
	public void openDoor(){
		if (!isTerminated)
			open = true;
		}
	
	/**
	 * A method to close a door
	 * 
	 * @post ...
	 * 		|new.isOpen() == false
	 */
	public void closeDoor(){
		if (!isTerminated)
		open = false;
	}
	
	/**
	 * A method to check whether or not a door is open
	 * 
	 * @return true if the door is open
	 */
	@Basic
	public boolean isOpen(){
		return open;
	}
	
	/**
	 * A method to the wall this door is set in
	 * 
	 * @return the wall this door is set in
	 */
	@Basic
	public Wall getWall(){
		return wall;
	}
	

	/**
	 * A method to check whether or not a door is set in a wall
	 * 
	 * @return true if the door is set in a wall
	 */
	public boolean hasWall(){
		if (wall != null)
			return true;
		return false;
	}
	
	/**
	 * A method to set the wall this door is to be set in
	 * 
	 * @post ...
	 * 		|if(isValidWall(wall))
	 * 		|then new.getWall() == wall
	 */
	@Basic @Raw
	void setWall(@Raw Wall wall){
		if(isValidWall(wall))
			this.wall = wall;
	}
	
	/**
	 * A method to set this door in a wall
	 *  
	 * @post ...
	 * 		|new.getWall() == wall
	 * @post ...
	 * 		|new.getWall().getDoor() == this
	 */
	public void setWallToDoor(Wall wall){
		wall.setDoor(this);
	}
	
	/**
	 * A method to check whether or not a wall is valid for this door
	 * 
	 * @param wall
	 * 			the wall you wish to set this door in
	 * @return true if this door is valid for this wall
	 */
	private boolean isValidWall(Wall wall) {
		return wall.isValidDoor(this);
	}

	/**
	 * A method to check whether or not a Door is terminated
	 * 
	 * @return true if the door is terminated
	 */
	@Basic @Raw
	public boolean isTerminated(){
		return isTerminated;
	}
	
	/**
	 * A method to terminate this door
	 * 
	 * @post ...
	 * 		|new.isTerminated() == true
	 * @post ...
	 * 		|new this.getWall().hasDoor() == false
	 */
	public void terminate(){
		isTerminated = true;
		if (hasWall())
			wall.setDoorNull();

	}

}
